/**
 * @author Justin Akin
 * @version Action Pals Core Library 0.1.0
 */
package com.actionpals.display
{	
	import flash.display.MovieClip;
	import flash.display.BitmapData;
	import flash.display.Bitmap;
	import flash.geom.Rectangle;
	import flash.geom.Matrix;
	import flash.geom.ColorTransform;
	import flash.display.Sprite;
	import com.actionpals.base.BaseSprite;
	import flash.display.DisplayObject;
	
	/**
	 * 
	 */
	public class Scale9Object extends BaseSprite
	{
				
	//--------------------------------------------------------------------------------
	//
	//	Protected Member Variables
	//
	//--------------------------------------------------------------------------------
		
		protected var _content:DisplayObject;
		protected var _container:Sprite;
				
		protected var _minWidth:Number;
		protected var _minHeight:Number;
		
		protected var _topRepeat:Boolean = false;
		protected var _bottomRepeat:Boolean = false;
		protected var _leftRepeat:Boolean = false;
		protected var _rightRepeat:Boolean = false;
		protected var _centerHRepeat:Boolean = false;
		protected var _centerVRepeat:Boolean = false;
		
		protected var _sourceRect:Rectangle;
		protected var _scaleRect:Rectangle;
		
		protected var _originalInfo:Scale9Info;
		protected var _resizedInfo:Scale9Info;
		
		protected var _bitmap:Bitmap;
		protected var _bitmapData:BitmapData;
		
	//--------------------------------------------------------------------------------
	//
	//	Constructor
	//
	//--------------------------------------------------------------------------------
	
		/**
		 * Constructor
		 */		
		public function Scale9Object( content:DisplayObject, scaleRect:Rectangle )
		{	
			_content = content;
			init();	
			this.scaleRect = scaleRect;		
		}
		
	//--------------------------------------------------------------------------------
	//
	//	Public Methods
	//
	//--------------------------------------------------------------------------------
		
		/**
		 * 
		 */
		public override function resize( width:Number, height:Number ):void
		{	
			_resizedInfo.resize( width, height );
			_bitmapData.dispose();
			_bitmapData = new BitmapData( width, height, true, 0x00000000 );
			
			drawBitmapData( _bitmapData, _originalInfo.topLeftRect, _resizedInfo.topLeftRect );
			drawBitmapData( _bitmapData, _originalInfo.topMiddleRect, _resizedInfo.topMiddleRect, _topRepeat );	
			drawBitmapData( _bitmapData, _originalInfo.topRightRect, _resizedInfo.topRightRect );	
			drawBitmapData( _bitmapData, _originalInfo.centerLeftRect, _resizedInfo.centerLeftRect, false, _leftRepeat );	
			drawBitmapData( _bitmapData, _originalInfo.centerMiddleRect, _resizedInfo.centerMiddleRect, _centerHRepeat, _centerVRepeat );	
			drawBitmapData( _bitmapData, _originalInfo.centerRightRect, _resizedInfo.centerRightRect, false, _rightRepeat );	
			drawBitmapData( _bitmapData, _originalInfo.bottomLeftRect, _resizedInfo.bottomLeftRect );	
			drawBitmapData( _bitmapData, _originalInfo.bottomMiddleRect, _resizedInfo.bottomMiddleRect, _bottomRepeat );	
			drawBitmapData( _bitmapData, _originalInfo.bottomRightRect, _resizedInfo.bottomRightRect );
			
			if( contains( _bitmap ) ) removeChild( _bitmap );
			
			_bitmap = addChild( new Bitmap( _bitmapData ) ) as Bitmap;	
		}
		
	//--------------------------------------------------------------------------------
	//
	//	Getters and Setters
	//
	//--------------------------------------------------------------------------------
		
		public function set topRepeat( value:Boolean ):void
		{	
			_topRepeat = value;	
		}
		
		public function set bottomRepeat( value:Boolean ):void
		{	
			_bottomRepeat = value;			
		}
		
		public function set leftRepeat( value:Boolean ):void
		{	
			_leftRepeat = value;			
		}
		
		public function set rightRepeat( value:Boolean ):void
		{	
			_rightRepeat = value;			
		}
		
		public function set centerHRepeat( value:Boolean ):void
		{	
			_centerHRepeat = value;	
		}
		
		public function set centerVRepeat( value:Boolean ):void
		{	
			_centerVRepeat = value;	
		}
		
		public function set scaleRect( scaleRect:Rectangle ):void
		{
			_scaleRect = scaleRect;
			_originalInfo = new Scale9Info( _sourceRect.clone(), _scaleRect.clone() );
			_resizedInfo = new Scale9Info( _sourceRect.clone(), _scaleRect.clone() );
		}
		
		public override function set width( value:Number ):void
		{
			resize( value, height );
		}
		
		public override function set height( value:Number ):void
		{
			resize( width, value );
		}
		
	//--------------------------------------------------------------------------------
	//
	//	Protected Methods
	//
	//--------------------------------------------------------------------------------
		
		/**
		 * 
		 */
		protected function init():void
		{	
			var w:Number = _content.width;
			var h:Number = _content.height;
			
			_container = new Sprite();
			_container.addChild( _content );
			
			_sourceRect = _container.getRect( _container );
			_scaleRect = _container.getRect( _container );
			_originalInfo = new Scale9Info( _sourceRect.clone(), _scaleRect.clone() );
			_resizedInfo = new Scale9Info( _sourceRect.clone(), _scaleRect.clone() );
			
			_bitmapData = new BitmapData( w, h, true, 0x00000000 );
			_bitmapData.draw( _container );
			_bitmap = addChild( new Bitmap( _bitmapData ) ) as Bitmap;
		}
		
		/**
		 * 
		 */
		protected function drawBitmapData( bitmapData:BitmapData, originalRect:Rectangle, resizedRect:Rectangle, repeatX:Boolean = false, repeatY:Boolean = false ):void
		{
			var rW:Number = resizedRect.width;
			var rH:Number = resizedRect.height;
			var rX:Number = resizedRect.x;
			var rY:Number = resizedRect.y;
			var oW:Number = originalRect.width;
			var oH:Number = originalRect.height;
			var oX:Number = originalRect.x;
			var oY:Number = originalRect.y;
			
			var matrix:Matrix;
			var colorTransform:ColorTransform = new ColorTransform();
			var blendMode:String = "normal";
			var smoothing:Boolean = true;
			
			var dW:Number = resizedRect.width / originalRect.width;
			var dH:Number = resizedRect.height / originalRect.height;
			var xTiles:int = repeatX ? Math.ceil( rW / oW ) : 1;
			var yTiles:int = repeatY ? Math.ceil( rH / oH ) : 1;
			
			var newW:Number = repeatX ? oW : rW;
			var newH:Number = repeatY ? oH : rH;
			var newX:Number;
			var newY:Number;
			var clipRect:Rectangle;
			var pattern:Bitmap;
			
			if( oW <= 0 || oH <= 0 || rW <= 0 || rH <= 0 ) return;
			
			_content.scaleX = repeatX ? 1 : dW;
			_content.scaleY = repeatY ? 1 : dH;
			
			pattern = createPattern( _container, originalRect, resizedRect, repeatX, repeatY );
			
			for( var i:int = 0; i < xTiles; i++ )
			{				
				for( var j:int = 0; j < yTiles; j++ )
				{					
					newX = ( oW * i ) + rX;
					newY = ( oH * j ) + rY;	
										
					matrix = new Matrix();
					matrix.translate( newX, newY );
					clipRect = new Rectangle( newX, newY, newW, newH );
					
					bitmapData.draw( pattern, matrix, colorTransform, blendMode, clipRect, smoothing );	
				}							
			}			
		}
		
		/**
		 * 
		 */
		protected function createPattern( source:DisplayObject, originalRect:Rectangle, resizedRect:Rectangle, repeatX:Boolean = false, repeatY:Boolean = false ):Bitmap
		{	
			var dW:Number = resizedRect.width / originalRect.width;
			var dH:Number = resizedRect.height / originalRect.height;
			var dX:Number = repeatX ? -originalRect.x : -( originalRect.x * dW );
			var dY:Number = repeatY ? -originalRect.y : -( originalRect.y * dH );
			var matrix:Matrix = new Matrix();
			var colorTransform:ColorTransform = new ColorTransform();
			var blendMode:String = "normal";
			var smoothing:Boolean = true;
			var w:Number = repeatX ? originalRect.width : resizedRect.width;
			var h:Number = repeatY ? originalRect.height : resizedRect.height;
			var patternData:BitmapData = new BitmapData( w, h, true, 0x00000000 );
			var clipRect:Rectangle = new Rectangle( 0, 0, w, h );
			
			
			matrix.translate( dX, dY );
			patternData.draw( source, matrix, colorTransform, blendMode, clipRect, smoothing );
			
			return new Bitmap( patternData );
		}				
	}	
}
